package com.colin.utils;

import com.colin.vo.DifferUtilResult;
import com.colin.vo.LineSignature;
import difflib.Delta;
import difflib.DiffUtils;
import difflib.Patch;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class FileCompareUtil {
	
	/*
	* @Description: filePath
	* @author 
	* @param @param oldFilePath
	* @param @param newFilePath
	* @param @return
	* @return List<ResultLine>
	 */
	public static List<LineSignature> compare(String oldFilePath, String newFilePath){
		List<String> oldFileL = FileUtil.readFile2List(new File(oldFilePath), "utf-8");
		List<String> newFileL = FileUtil.readFile2List(new File(newFilePath), "utf-8");
		
		return compare(oldFileL, newFileL);
	}

	/*
	* @Description: return all lines, include increase, decrease, nochanged
	* @author 
	* @param @param oldFileL
	* @param @param newFileL
	* @param @return
	* @return List<ResultLine>
	 */
	public static List<LineSignature> compare(List<String> oldFileL, List<String> newFileL) {
		List<LineSignature> resultLine = new ArrayList<LineSignature>();
		if(oldFileL == null || oldFileL.size() == 0 || newFileL == null || newFileL.size() == 0){
			return resultLine;
		}
		
		Patch<String> result = DiffUtils.diff(oldFileL, newFileL);
		List<Delta<String>> deltas = result.getDeltas();

		Position position = new Position();
		for (Delta<String> detal : deltas) {
			dealWithChange(detal,resultLine, oldFileL, position);
		}
		int oldNum = position.getOldNum();
		int newNum = position.getNewNum();
		
		for (; oldNum < oldFileL.size(); oldNum++, newNum++) {
			LineSignature result2 = new LineSignature(oldNum + 1 + "", newNum + 1+ "", "", oldFileL.get(oldNum));
			resultLine.add(result2);
		}
		
		return resultLine;
	}

	/*
	* @Description:return all lines and Patch
	* @author 
	* @param @param oldFileL
	* @param @param newFileL
	* @param @return
	* @return DifferUtilResult
	 */
	public static DifferUtilResult compare2(List<String> oldFileL, List<String> newFileL) {
		DifferUtilResult differResult = new DifferUtilResult();
		List<LineSignature> resultLine = new ArrayList<LineSignature>();
		if(oldFileL == null || oldFileL.size() == 0 || newFileL == null || newFileL.size() == 0){
			return differResult;
		}
		
		Patch<String> result = DiffUtils.diff(oldFileL, newFileL);
		List<Delta<String>> deltas = result.getDeltas();

		Position position = new Position();
		for (Delta<String> detal : deltas) {
			dealWithChange(detal,resultLine, oldFileL, position);
		}
		int oldNum = position.getOldNum();
		int newNum = position.getNewNum();
		
		for (; oldNum < oldFileL.size(); oldNum++, newNum++) {
			LineSignature result2 = new LineSignature(oldNum + 1 + "", newNum + 1+ "", "", oldFileL.get(oldNum));
			resultLine.add(result2);
		}
		differResult.setPatch(result);
		differResult.setResultLines(resultLine);
		return differResult;
	}
	/*
	* @Description:deal with change point
	* @author 
	* @param @param detal
	* @param @param resultLine
	* @param @param oldFileL
	* @param @param positionIn
	* @return void
	 */
	private static void dealWithChange(Delta<String> detal, List<LineSignature> resultLine, List<String> oldFileL, Position positionIn) {
		int oldNum = positionIn.getOldNum();
		int newNum = positionIn.getNewNum();
		
		int position = detal.getOriginal().getPosition();
		int size = detal.getOriginal().getLines().size();
		List<String> lines = detal.getOriginal().getLines();
		if (size > 0) {
			// print no change
			for (; oldNum < position; oldNum++, newNum++) {
				LineSignature result = new LineSignature(oldNum + 1 + "", newNum + 1+ "", "", oldFileL.get(oldNum));
				resultLine.add(result);
			}
			for (int i = position; i < position + size; i++, oldNum++) {
				LineSignature result = new LineSignature(i + 1 + "", "", "-",oldFileL.get(i));
				resultLine.add(result);
			}
		}
		int positionAdd = detal.getRevised().getPosition();
		int sizeAdd = detal.getRevised().getLines().size();
		List<String> linesAdd = detal.getRevised().getLines();
		if (sizeAdd > 0) {
			// print no change
			for (; newNum < positionAdd; oldNum++, newNum++) {
				LineSignature result = new LineSignature(oldNum + 1 + "", newNum + 1+ "", "", oldFileL.get(oldNum));
				resultLine.add(result);
			}
			for (int i = 0; i < sizeAdd; i++, newNum++) {
				LineSignature result = new LineSignature("", (newNum + 1) + "", "+",linesAdd.get(i));
				resultLine.add(result);
			}
		}
		
		positionIn.setOldNum(oldNum);
		positionIn.setNewNum(newNum);
	}
	
	static class Position{
		private int oldNum;
		private int newNum;
		public int getOldNum() {
			return oldNum;
		}
		public void setOldNum(int oldNum) {
			this.oldNum = oldNum;
		}
		public int getNewNum() {
			return newNum;
		}
		public void setNewNum(int newNum) {
			this.newNum = newNum;
		}
	}
	
	private static void printChange(Delta<String> detal) {
		int position = detal.getOriginal().getPosition();
		int size = detal.getOriginal().getLines().size();
		System.out.println("=============================" + position
				+ "-------" + size);

		// +
		int positionAdd = detal.getRevised().getPosition();
		int sizeAdd = detal.getRevised().getLines().size();
		System.out.println("=============================" + positionAdd
				+ "++++++++" + sizeAdd);
		System.out.println("***********************************************");
	}

	
	public static void main(String[] args) {

		List<String> oldFileL = FileUtil.readFile2List(new File(
				"E:/shell/solution_parameter.sql"), "utf-8");
		List<String> newFileL = FileUtil.readFile2List(new File(
				"E:/shell/solution_parameter123.sql"), "utf-8");
		List<LineSignature> resultLine = FileCompareUtil.compare(oldFileL, newFileL);
		DifferUtilResult result = FileCompareUtil.compare2(oldFileL, newFileL);
	/*	for (Delta tmp : result.getPatch().getDeltas()) {
			System.out.println(tmp);
		}*/


		for (LineSignature tmp : resultLine) {
			System.out.println(tmp);
		}
	}
	
}
